package com.unionpay.fsas.demo.nonbank;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.unionpay.fsas.sdk.FsasService;
import com.unionpay.fsas.sdk.LogUtil;
import com.unionpay.fsas.sdk.SDKConfig;

/**
 * 重要：联调测试时请仔细阅读注释！
 * 产品：资金结算接入系统<br>
 * 交易：商户资金结算（单笔）：<br>
 * 日期： 2018-02<br>
 * 参考《中国银联资金结算接入系统技术指南 第1部分 交易及报文接口（支付机构适用）》第5.4章节
 */
public class Form_5_04_SingleFundSettlement extends HttpServlet {


	/**
     * 
     */
    private static final long serialVersionUID = 8011644545941313046L;

    @Override
	public void init(ServletConfig config) throws ServletException {
		/**
		 * 请求银联接入地址，获取证书文件，证书路径等相关参数初始化到SDKConfig类中
		 * 在java main 方式运行时必须每次都执行加载
		 * 如果是在web应用开发里,这个方法可使用监听的方式写入缓存,无须在这出现
		 */
		//这里已经将加载属性文件的方法挪到了web/AutoLoadServlet.java中
		//SDKConfig.getConfig().loadPropertiesFromSrc(); //从classpath加载fsas_sdk.properties文件
		super.init();
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		

		
        String merId = req.getParameter("merId");
        String merName = req.getParameter("merName");
        String acqInsCode = req.getParameter("acqInsCode");//机构代码
        String txnNo = req.getParameter("txnNo");//交易流水号
        String txnDate = req.getParameter("txnDate");//交易日期
        String txnAmt = req.getParameter("txnAmt");//交易金额
        /*** 付款方信息***/
        String payerMerName = req.getParameter("payerMerName");//付款商户名称
        String payerMerId = req.getParameter("payerMerId");//付款商户代码
        String payerAcctNo = req.getParameter("payerAcctNo");//付款方账号
        String payerAcctName = req.getParameter("payerAcctName");//付款方账户名称
        /***收款方信息***/
        String payeeBankNo = req.getParameter("payeeBankNo");//收款方开户行行号 
        String payeeAccType = req.getParameter("payeeAccType");//收款方账号类型
        String payeeAcctNo = req.getParameter("payeeAcctNo");//收款方账号
        String payeeAcctName = req.getParameter("payeeAcctName");//收款方账户名称

		
		Map<String, String> contentData = new HashMap<String, String>();

		/***银联资金结算接入系统，产品参数，除了encoding自行选择外其他不需修改***/
		contentData.put("version", DemoBase.version);                  //版本号
		contentData.put("encoding", DemoBase.encoding);             //字符集编码 可以使用UTF-8,GBK两种方式
		contentData.put("signMethod", SDKConfig.getConfig().getSignMethod()); //签名方法
		 
		 contentData.put("txnType", "02");                                   //交易类型 02-商户资金结算（单笔）
         contentData.put("txnNo", txnNo);                                    //交易流水号
         contentData.put("acqInsCode", acqInsCode);                    //机构代码
         contentData.put("txnDate", txnDate);                               //交易日期
         contentData.put("sndTime", DemoBase.getSendTime());      //发送时间 格式HHmmss
         contentData.put("settleMethod", "00");                           //结算方式  00:T+0付款01:T+N(N>0)付款02:收入费用结转03:客户赎回04：提现06: 预付费卡05：其他
         contentData.put("merId", merId);                                    //商户号
         contentData.put("merName", merName);                           //商户名称

         /***收款方信息***/
         contentData.put("payeeBankNo", payeeBankNo);                //收款方开户行行 号当payeeAccType=01时，可以为空；其他情况必填
         contentData.put("payeeAcctNo", payeeAcctNo);                //收款方账号       
         contentData.put("payeeAccType", payeeAccType);              //选填字段 收款方账号类型
         contentData.put("payeeAcctName", payeeAcctName);        //收款方账户名称
       
         /***付款方信息***/
         contentData.put("payerAcctNo", payerAcctNo);   //付款放账号 与付款方账户名称同时出现或者同时不出现   可选字段 
         contentData.put("payerAcctName", payerAcctName);//付款放账号名称 与付款方账号同时出现或者同时不出现  可选字段 
         contentData.put("payerMerName", payerMerName);   //付款商户名称    可选字段 
         contentData.put("payerMerId", payerMerId);//付款商户代码  可选字段 

         contentData.put("currencyCode", "156");                          //币种 
         contentData.put("txnAmt", txnAmt);                                  //金额
         contentData.put("busPdtFlag", "busPdtFlag");                    //业务产品标识 具体值参考字段说明
	    
         /***选填域***/
         contentData.put("remark", "");   //附言  选填
         contentData.put("summary", ""); //业务摘要 选填
         contentData.put("reqReserved", "");  //请求放保留域 选填
         contentData.put("reserved", "");    //保留域   选填
         contentData.put("regionCd", "2900");  //地区代码（4位地区编号）选填
         
		/**对请求参数进行签名并发送http post请求，接收同步应答报文**/
		Map<String, String> reqData = FsasService.sign(contentData,DemoBase.encoding);			//报文中certId,signature的值是在signData方法中获取并自动赋值的，只要证书配置正确即可。
		String requestBackUrl = SDKConfig.getConfig().getBackRequestUrl();   			                //交易请求url从配置文件读取对应属性文件fsas_sdk.properties中的 fsassdk.backTransUrl
		Map<String, Object> rspData = FsasService.doPost(reqData,requestBackUrl,DemoBase.encoding); //发送请求报文并接受同步应答（默认连接超时时间30秒，读取返回结果超时时间30秒）;这里调用signData之后，调用submitUrl之前不能对submitFromData中的键值对做任何修改，如果修改会导致验签不通过
		
		/**对应答码的处理，请根据您的业务逻辑来编写程序,以下应答码处理逻辑仅供参考------------->**/
		StringBuffer parseStr = new StringBuffer("");
		if(!rspData.isEmpty()){
			if(FsasService.validateNew(rspData, DemoBase.encoding)){
				LogUtil.writeLog("验证签名成功");
				String respCode = rspData.get("respCode").toString() ;
				if(("00").equals(respCode)){
					//成功 
					//TODO
				}else{
					//其他应答码为失败请排查原因
					//TODO
				}
			}else{
				LogUtil.writeErrorLog("验证签名失败");
				//TODO 检查验证签名失败的原因
			}
		}else{
			//未返回正确的http状态
			LogUtil.writeErrorLog("未获取到返回报文或返回http状态码非200");
		}
		String reqMessage = DemoBase.genHtmlResult(reqData);
		String rspMessage = DemoBase.genHtmlResultNew(rspData);
		resp.getWriter().write("商户资金结算（单笔）交易请求报文:<br/>"+reqMessage+"<br/>" + "应答报文:</br>"+rspMessage+parseStr);
		
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doPost(req, resp);
	}
}
